package com.un.ebs.production.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.core.exception.BusinessEntityNotFoundException;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.product.enums.ProductPurchaseTypeEnum;
import com.un.ebs.product.service.ProductSkuService;
import com.un.ebs.production.domain.*;
import com.un.ebs.production.dto.ProductionSeqDto;
import com.un.ebs.production.dto.ProductionSeqItemDto;
import com.un.ebs.production.enums.QualityCheckPlanTypeEnum;
import com.un.ebs.production.mapper.*;
import com.un.ebs.production.service.ProductionSeqService;
import com.un.ebs.sys.service.DictionaryValueService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (ProductionSeq)表服务实现类
 *
 * @author liubo
 * @since 2020-07-06 16:27:16
 */
@Service("productionSeqService")
public class ProductionSeqServiceImpl extends ServiceImpl<ProductionSeqMapper, ProductionSeq> implements ProductionSeqService {

    @Resource
    private DictionaryValueService dictionaryValueService;

    @Resource
    private ProductionSeqExtMapper productionSeqExtMapper;

    @Resource
    private ProductionSeqItemMapper productionSeqItemMapper;

    @Resource
    private ProductionSeqItemExtMapper productionSeqItemExtMapper;

    @Resource
    private ProductionSeqItemViewMapper productionSeqItemViewMapper;

    @Resource
    private ProductSkuService productSkuService;

    @Override
    public String add(ProductionSeqDto req) {
        return save(req);
    }

    @Override
    public void update(ProductionSeqDto req) {
        save(req);
    }

    @Transactional
    public String save(ProductionSeqDto req) {

        ProductionSeq obj;
        if (StringUtils.isNullOrEmpty(req.getId())) {
            obj = new ProductionSeq();
        } else {
            obj = getById(req.getId());
            if (obj == null) {
                throw new BusinessEntityNotFoundException(req.getId(), "工艺");
            }
        }
        obj.setName(req.getName());
        obj.insertOrUpdate();

        productionSeqItemMapper.deleteBatchIds(req.getItems().stream().map(s -> s.getId()).collect(Collectors.toList()));
        if (!StringUtils.isNullOrEmpty(req.getItems())) {
            for (ProductionSeqItemDto item : req.getItems()) {

                switch (item.getCheckPlanType()) {
                    case Default:
                    case All:
                        item.setCheckPlanQty(null);
                        break;
                    case Proportion:
                    case Ration:
                        if (item.getCheckPlanQty() == null) {
                            throw new BusinessException("检验数量不能为空。");
                        }
                        if (item.getCheckPlanQty() == 0) {
                            throw new BusinessException("检验数量不能为0.");
                        }
                        if (item.getCheckPlanType() == QualityCheckPlanTypeEnum.Proportion && item.getCheckPlanQty() > 100) {
                            throw new BusinessException("检验比例不能超过 100% ");
                        }
                        break;
                    default:
                        throw new BusinessException("质检类别定义异常。");
                }

                ProductionSeqItem objItem = new ProductionSeqItem();
                objItem.setCode(item.getCode());
                objItem.setName(item.getName());
                objItem.setRoleId(item.getRoleId());
                objItem.setRemark(item.getRemark());
                objItem.setSeqType(item.getSeqType());
                objItem.setCheckPlanType(item.getCheckPlanType());
                objItem.setCheckPlanQty(item.getCheckPlanQty());
                objItem.setWorkMinute(item.getWorkMinute());
                objItem.setSeqId(obj.getId());
                objItem.insert();
            }
        }
        return obj.getId();
    }

    @Transactional
    @Override
    public void copyTo(String seqId, String newName) {
        ProductionSeq obj = baseMapper.selectById(seqId);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(seqId, "工序标准");
        }
        if (StringUtils.isNullOrEmpty(newName)) {
            throw new BusinessException("请填写新工序标准名称。");
        }
        List<ProductionSeqItem> items = queryItem(seqId, -1, 1).getRecords();
        if (StringUtils.isNullOrEmpty(items)) {
            throw new BusinessException("工序内容为空。");
        }

        ProductionSeq objNew = new ProductionSeq();
        objNew.setName(newName);
        objNew.insert();

        for (ProductionSeqItem item : items) {
            ProductionSeqItem objItem = new ProductionSeqItem();
            String itemId = objItem.getId();
            BeanUtils.copyProperties(item, objItem);
            objItem.setId(null);
            objItem.setSeqId(objNew.getId());
            objItem.insert();
        }
    }

    @Override
    public void addSeq(String name) {
        ProductionSeq obj = new ProductionSeq();
        obj.setName(name);
        obj.insert();
    }

    @Override
    public void updateSeq(String id, String name) {
        ProductionSeq obj;
        if (StringUtils.isNullOrEmpty(id)) {
            obj = new ProductionSeq();
        } else {
            obj = baseMapper.selectById(id);
        }
        obj.setName(name);
        obj.insertOrUpdate();
    }

    @Override
    public ProductionSeqExt queryById(String id) {
        return productionSeqExtMapper.selectById(id);
    }

    @Override
    public ProductionSeqItemView queryItemById(String id) {
        return productionSeqItemViewMapper.selectById(id);
    }

    @Override
    public IPage<ProductionSeqItemView> queryItemViewBySeq(String seqId, int pageSize, int pageIndex) {
        Page<ProductionSeqItemView> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionSeqItemView> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionSeqItemView::getSeqId, seqId);
        lq.orderByAsc(ProductionSeqItemView::getCode);
        return productionSeqItemViewMapper.selectPage(page, lq);
    }

    @Override
    public void addSeqItem(ProductionSeqItemDto req) {
        saveSeqItem(req);
    }

    @Override
    public void updateSeqItem(ProductionSeqItemDto req) {
        saveSeqItem(req);
    }

    @Override
    public void delete(String id) {
        baseMapper.deleteById(id);
    }

    @Override
    public void deleteItem(String itemId) {
        productionSeqItemMapper.deleteById(itemId);
    }

    public void saveSeqItem(ProductionSeqItemDto req) {
        ProductionSeqItem item;
        if (StringUtils.isNullOrEmpty(req.getId())) {
            item = new ProductionSeqItem();
        } else {
            item = productionSeqItemMapper.selectById(req.getId());
            if (item == null) {
                throw new BusinessEntityNotFoundException(req.getId(), "工艺序号");
            }
        }
        if (req.getPurchaseType() == ProductPurchaseTypeEnum.Purchase) {
            if (StringUtils.isNullOrEmpty(req.getSkuId())) {
                throw new BusinessException("委外工序，请指定采购需求物料。");
            }
        } else {
            req.setSkuId(null);
        }

        switch (req.getCheckPlanType()) {
            case Default:
            case All:
                item.setCheckPlanQty(null);
                break;
            case Proportion:
            case Ration:
                if (item.getCheckPlanQty() == null) {
                    throw new BusinessException(String.format("质检数量方式为【%s】时，质检数量设置值不能为空。", req.getCheckPlanType().getDesc()));
                }
                if (item.getCheckPlanQty() == 0) {
                    throw new BusinessException(String.format("质检数量方式为【%s】时，质检数量设置值不能为0。", req.getCheckPlanType().getDesc()));
                }
                if (item.getCheckPlanType() == QualityCheckPlanTypeEnum.Proportion && item.getCheckPlanQty() > 100) {
                    throw new BusinessException(String.format("质检数量方式为【%s】时，检验比例不能超过 100% 。", req.getCheckPlanType().getDesc()));
                }
                break;
            default:
                throw new BusinessException("质检类别定义异常。");
        }

        item.setCode(req.getCode());
        item.setName(req.getName());
        item.setSeqId(req.getSeqId());
        item.setSeqType(req.getSeqType());
        item.setCheckPlanQty(req.getCheckPlanQty());
        item.setCheckPlanType(req.getCheckPlanType());
        item.setWorkMinute(req.getWorkMinute());
        item.setRemark(req.getRemark());
        item.setRoleId(req.getRoleId());
        item.setPurchaseType(req.getPurchaseType());
        item.setRelationSkuId(req.getSkuId());
        item.setRelationUserQty(req.getUserQty());
        item.insertOrUpdate();
    }

    @Override
    public IPage<ProductionSeqItem> queryItem(String id, int pageSize, int pageIndex) {
        Page<ProductionSeqItem> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionSeqItem> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionSeqItem::getSeqId, id);
        lq.orderByAsc(ProductionSeqItem::getCode);
        return productionSeqItemMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionSeqItemExt> queryItemView(String seqId, int pageSize, int pageIndex) {
        Page<ProductionSeqItemExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionSeqItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(ProductionSeqItemExt::getSeqId, seqId);
        lq.orderByAsc(ProductionSeqItemExt::getCode);
        return productionSeqItemExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<ProductionSeqExt> query(String searchText, int pageSize, int pageIndex) {
        Page<ProductionSeqExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<ProductionSeqExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(ProductionSeqExt::getName, searchText);
        }
        lq.eq(ProductionSeqExt::getIsDelete, false);
        lq.orderByAsc(ProductionSeqExt::getName);
        return productionSeqExtMapper.selectPage(page, lq);
    }
}